<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>用户管理 - 信院数字人后台</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <style>
        :root{--color-primary:#003366;--color-danger:#d7000f;--color-border:#d0d0d0;--color-row-hover:#f5f7fa;}
        body{font-family:"Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background:#f3f4f6;font-size:14px;}
        .sidebar{width:240px;background:#001529;color:#c7d0d9;display:flex;flex-direction:column;}
        .sidebar .logo{height:64px;display:flex;align-items:center;justify-content:center;font-size:18px;font-weight:600;background:#002140;color:#fff;padding:0 16px;}
        .sidebar .logo img{width:40px;height:40px;border-radius:50%;margin-right:12px;object-fit:contain;background:#fff;padding:2px;}
        .sidebar .menu a{display:block;padding:12px 24px;font-size:14px;transition:background .2s;}
        .sidebar .menu a:hover,.sidebar .menu a.active{background:#1890ff;color:#fff;}
        .topbar{height:64px;background:#fff;border-bottom:1px solid var(--color-border);padding:0 24px;display:flex;align-items:center;justify-content:space-between;}
        .btn{display:inline-flex;align-items:center;justify-content:center;padding:6px 16px;font-size:14px;border:1px solid var(--color-border);background:#fff;cursor:pointer;transition:all .2s;border-radius:4px;}
        .btn-primary{background:var(--color-primary);color:#fff;border-color:var(--color-primary);}
        .btn-primary:hover{background:#004080;}
        .btn-danger{color:var(--color-danger);border-color:var(--color-danger);}
        .btn-danger:hover{background:var(--color-danger);color:#fff;}
        .data-table{width:100%;border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid var(--color-border);}
        .data-table thead{background-color:#f5f7fa;color:#333;}
        .data-table th,.data-table td{padding:12px 16px;border-bottom:1px solid var(--color-border);border-right:1px solid var(--color-border);text-align:left;word-break:break-all;line-height:1.4;vertical-align:middle;}
        .data-table th:last-child,.data-table td:last-child{border-right:none;}
        .data-table tr:hover{background-color:var(--color-row-hover);}
        .data-table th.id-col{width:60px;}.data-table th.avatar-col{width:100px;}.data-table th.name-col{width:140px;}.data-table th.id-number-col{width:160px;}
        .data-table th.status-col{width:100px;}.data-table th.time-col{width:160px;}.data-table th.action-col{width:100px;text-align:center;}
        .data-table td.action-col{text-align:center;}
        .action-btn{display:inline-block;width:28px;height:28px;line-height:28px;text-align:center;border-radius:4px;margin:0 4px;cursor:pointer;transition:all .2s;color:#666;border:1px solid transparent;}
        .action-btn:hover{background-color:#f0f0f0;border-color:#ddd;}
        .action-btn.edit{color:#1890ff;}.action-btn.edit:hover{background-color:#e6f7ff;border-color:#bae7ff;}
        .action-btn.delete{color:#ff4d4f;}.action-btn.delete:hover{background-color:#fff2f0;border-color:#ffccc7;}
        .avatar-img{width:48px;height:48px;border-radius:50%;object-fit:cover;border:1px solid #eee;}
        .status-badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:12px;}
        .status-normal{background:#e6f7ff;color:#1890ff;}
        .status-banned{background:#fff2f0;color:#ff4d4f;}
        .status-frozen{background:#fffbe6;color:#faad14;}
        .modal-mask{position:fixed;inset:0;background:rgba(0,0,0,.45);display:flex;align-items:center;justify-content:center;z-index:999;opacity:0;pointer-events:none;transition:opacity .3s;}
        .modal-mask.show{opacity:1;pointer-events:auto;}
        .modal-box{background:#fff;width:640px;max-width:90vw;max-height:90vh;overflow:auto;display:flex;flex-direction:column;border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,0.15);}
        .modal-header{padding:16px 24px;border-bottom:1px solid var(--color-border);font-size:16px;font-weight:600;}
        .modal-footer{padding:12px 24px;border-top:1px solid var(--color-border);text-align:right;}
        .form-input{width:100%;padding:7px 11px;border:1px solid var(--color-border);font-size:14px;transition:border-color .2s;border-radius:4px;}
        .form-input:focus{border-color:var(--color-primary);outline:none;box-shadow:0 0 0 2px rgba(0,51,102,.2);}
        .pagination{font-size:14px;display:flex;align-items:center;gap:8px;}
        .pagination .btn:disabled{opacity:.6;cursor:not-allowed;}
        main {padding-bottom:60px !important;}
        #page {position:fixed;bottom:0;left:0;right:0;background:white;z-index:10;border-top:1px solid var(--color-border);box-shadow:0 -2px 8px rgba(0,0,0,0.05);}
    </style>
</head>
<body class="flex h-screen overflow-hidden">
<aside class="sidebar">
    <div class="logo">
        <img src="/logo/logo.jpg" alt="logo" onerror="this.src='https://picsum.photos/40/40?random=logo';this.style.background='#fff';">
        信院数字人后台
    </div>
    <nav class="menu flex-1 pt-4">
        <a href="/admin/usersManage.html" class="active"><i class="fa fa-user-o mr-2"></i>用户管理</a>
        <a href="/admin/postsManage.html"><i class="fa fa-comments-o mr-2"></i>言论详情</a>
        <a href="/admin/imagesManage.html"><i class="fa fa-image mr-2"></i>图片管理</a>
        <a href="/admin/filesManage.html"><i class="fa fa-file-o mr-2"></i>文件管理</a>
    </nav>
</aside>

<section class="flex-1 flex flex-col">
    <header class="topbar">
        <div class="text-base font-medium">用户管理</div>
        <div class="flex items-center gap-4"><span class="text-sm">管理员</span><img src="/logo/guanliyuan.png" class="w-8 h-8 rounded-full"></div>
    </header>

    <main class="flex-1 overflow-y-auto p-6">
        <div class="bg-white border border-gray-200 rounded px-4 py-3 mb-4 flex items-center justify-between">
            <div class="flex items-center gap-4">
                <input id="keyword" type="text" placeholder="请输入昵称或学号/工号" class="form-input w-64">
                <select id="statusFilter" class="form-input w-32">
                    <option value="">全部状态</option>
                    <option value="0">正常</option>
                    <option value="1">封禁</option>
                    <option value="2">冻结</option>
                </select>
                <button id="searchBtn" class="btn btn-primary">查询</button>
                <button id="resetBtn" class="btn">重置</button>
            </div>
            <button id="addBtn" class="btn btn-primary" onclick="showAddModal()"><i class="fa fa-plus mr-1"></i>新增用户</button>
        </div>

        <div class="bg-white rounded overflow-x-auto shadow-sm">
            <table class="data-table min-w-[940px]">
                <thead>
                <tr>
                    <th class="id-col">ID</th>
                    <th class="avatar-col">头像</th>
                    <th class="name-col">昵称</th>
                    <th class="id-number-col">学号/工号</th>
                    <th class="status-col">状态</th>
                    <th class="time-col">注册时间</th>
                    <th class="time-col">更新时间</th>
                    <th class="action-col">操作</th>
                </tr>
                </thead>
                <tbody id="list"></tbody>
            </table>
        </div>
    </main>

    <div id="page" class="px-4 py-3 flex items-center justify-between text-sm text-gray-600">
        <div>共 <span id="total">0</span> 条</div>
        <div class="pagination">
            <button id="prev" class="btn">上一页</button>
            <span>第 <span id="curr">1</span> 页 / 共 <span id="pages">1</span> 页</span>
            <button id="next" class="btn">下一页</button>
        </div>
    </div>
</section>

<!-- 新增/编辑模态框 -->
<div id="formModal" class="modal-mask">
    <div class="modal-box">
        <div class="modal-header">
            <span id="modalTitle">新增用户</span>
            <button class="btn btn-sm ml-auto" onclick="hideFormModal()"><i class="fa fa-times"></i></button>
        </div>
        <div id="form" class="px-6 py-4 space-y-4">
            <input type="hidden" id="id">
            <div>
                <label class="block text-sm font-medium mb-1">昵称 <span class="text-red-600">*</span></label>
                <input type="text" id="nickName" class="form-input" placeholder="请输入昵称" required>
            </div>
            <div>
                <label class="block text-sm font-medium mb-1">学号/工号 <span class="text-red-600">*</span></label>
                <input type="text" id="stuOrTeaId" class="form-input" placeholder="请输入学号或教职工编号" required>
            </div>
            <div>
                <label class="block text-sm font-medium mb-1">密码 <span class="text-red-600">*</span></label>
                <input type="password" id="userPass" class="form-input" placeholder="请输入密码" required>
            </div>
            <div>
                <label class="block text-sm font-medium mb-1">头像</label>
                <div id="avatarUploadBox" class="border border-dashed border-gray-400 rounded p-4 text-center cursor-pointer">
                    <input type="file" id="avatarFile" accept="image/*" class="hidden">
                    <i class="fa fa-cloud-upload text-2xl text-gray-400 mb-1"></i>
                    <p class="text-gray-500 text-sm">点击上传头像</p>
                </div>
                <div id="avatarPreview" class="mt-2 hidden">
                    <img class="w-20 h-20 rounded-full object-cover border">
                </div>
            </div>
            <div>
                <label class="block text-sm font-medium mb-1">状态 <span class="text-red-600">*</span></label>
                <select id="accountStatus" class="form-input" required>
                    <option value="0">正常</option>
                    <option value="1">封禁</option>
                    <option value="2">冻结</option>
                </select>
            </div>
        </div>
        <div class="modal-footer">
            <button type="button" class="btn" onclick="hideFormModal()">取消</button>
            <button type="button" id="saveBtn" class="btn btn-primary">保存</button>
        </div>
    </div>
</div>

<!-- 删除确认框 -->
<div id="delModal" class="modal-mask">
    <div class="modal-box max-w-sm">
        <div class="modal-header">删除确认</div>
        <div class="p-6 text-center text-sm text-gray-700">此操作不可撤销，确定删除？</div>
        <div class="modal-footer">
            <button class="btn" onclick="hideDelModal()">取消</button>
            <button id="delConfirm" class="btn btn-danger">删除</button>
        </div>
    </div>
</div>

<script>
    /* ---------- 工具 ---------- */
    const $ = q => document.querySelector(q);
    const modalForm = $('#formModal'), modalDel = $('#delModal');
    let currPage = 1, pageSize = 6, delId = 0, totalPages = 1;

    /* 通用 fetch */
    async function request(url, option = {}) {
        const headers = { 'Content-Type': 'application/json', ...option.headers };
        const body = option.body && typeof option.body === 'object' ? JSON.stringify(option.body) : option.body;
        const res = await fetch(url, { ...option, headers, body, credentials: 'include' });
        if (!res.ok) throw new Error(await res.text());
        const ct = res.headers.get('content-type');
        return ct && ct.includes('application/json') ? res.json() : res.text();
    }

    /* 状态小工具 */
    const statusTextMap = { 0: '正常', 1: '封禁', 2: '冻结' };
    const statusClassMap = { 0: 'status-normal', 1: 'status-banned', 2: 'status-frozen' };
    function getStatusText(s) { return statusTextMap[s] || '未知'; }
    function getStatusClass(s) { return statusClassMap[s] || ''; }

    /* 唯一数据入口 */
    async function loadTable() {
        const kw = $('#keyword').value.trim();
        const status = $('#statusFilter').value;
        const params = new URLSearchParams({ pageNum: currPage, pageSize, keyword: kw, status });
        try {
            const res = await request('/api/admin/users?' + params);
            const list = res.records || [], total = res.total || 0;
            totalPages = Math.max(1, Math.ceil(total / pageSize));
            let html = '';
            list.forEach(r => {
                html += `<tr>
                    <td class="id-col">${r.id}</td>
                    <td class="avatar-col"><img src="${r.imageUrl || '/logo/avatar.png'}" class="avatar-img"></td>
                    <td class="name-col">${r.nickName}</td>
                    <td class="id-number-col">${r.stuOrTeaId}</td>
                    <td class="status-col"><span class="status-badge ${getStatusClass(r.accountStatus)}">${getStatusText(r.accountStatus)}</span></td>
                    <td class="time-col">${r.registerTime || '-'}</td>
                    <td class="time-col">${r.updateTime || '-'}</td>
                    <td class="action-col">
                        <span class="action-btn edit" title="编辑" onclick="editRow(${r.id})"><i class="fa fa-pencil"></i></span>
                        <span class="action-btn delete" title="删除" onclick="delRow(${r.id})"><i class="fa fa-trash-o"></i></span>
                    </td>
                </tr>`;
            });
            $('#list').innerHTML = html || '<tr><td colspan="8" class="text-center text-gray-400 py-8">暂无数据</td></tr>';
            $('#total').textContent = total;
            $('#curr').textContent = currPage;
            $('#pages').textContent = totalPages;
            $('#prev').disabled = currPage === 1;
            $('#next').disabled = currPage === totalPages;
        } catch (e) { alert('加载表格失败：' + e.message); }
    }

    /* 分页按钮 */
    $('#prev').onclick = () => { if (currPage > 1) { currPage--; loadTable(); } };
    $('#next').onclick = () => { if (currPage < totalPages) { currPage++; loadTable(); } else alert('已经是最后一页啦！'); };

    /* 弹窗控制 */
    function showAddModal() {
        $('#id').value = '';
        $('#nickName').value = $('#stuOrTeaId').value = $('#userPass').value = '';
        $('#accountStatus').value = '0';
        $('#avatarFile').value = '';
        $('#avatarPreview').classList.add('hidden');
        $('#modalTitle').textContent = '新增用户';
        modalForm.classList.add('show');
    }
    function hideFormModal() { modalForm.classList.remove('show'); }
    function hideDelModal() { modalDel.classList.remove('show'); }

    /* 编辑 */
    async function editRow(id) {
        try {
            const row = await request(`/api/admin/users/${id}`);
            $('#id').value = row.id;
            $('#nickName').value = row.nickName;
            $('#stuOrTeaId').value = row.stuOrTeaId;
            $('#userPass').value = row.userPass;
            $('#accountStatus').value = row.accountStatus;
            if (row.imageUrl) {
                $('#avatarPreview img').src = row.imageUrl;
                $('#avatarPreview').classList.remove('hidden');
            } else $('#avatarPreview').classList.add('hidden');
            $('#modalTitle').textContent = '编辑用户';
            modalForm.classList.add('show');
        } catch (e) { alert('加载编辑数据失败：' + e.message); }
    }

    /* 保存 */
    $('#saveBtn').onclick = async () => {
        try {
            const id = $('#id').value.trim();
            const nickName = $('#nickName').value.trim();
            const stuOrTeaId = $('#stuOrTeaId').value.trim();
            const userPass = $('#userPass').value.trim();
            const accountStatus = $('#accountStatus').value;
            const avatarFile = $('#avatarFile').files[0];
            if (!nickName || !stuOrTeaId || !userPass) return alert('请填写所有必填项');

            const body = {
                nickName,
                stuOrTeaId,
                userPass,
                accountStatus: parseInt(accountStatus),
                imageUrl: null
            };
            if (avatarFile) {
                body.imageUrl = await new Promise((resolve, reject) => {
                    const reader = new FileReader();
                    reader.onload = e => resolve(e.target.result);
                    reader.onerror = reject;
                    reader.readAsDataURL(avatarFile);
                });
            }
            await request(id ? `/api/admin/users/${id}` : '/api/admin/users', { method: id ? 'PUT' : 'POST', body });
            hideFormModal(); loadTable();
            alert(id ? '用户编辑成功' : '用户新增成功');
        } catch (e) { alert('保存失败：' + e.message); }
    };

    /* 删除 */
    function delRow(id) { delId = id; modalDel.classList.add('show'); }
    $('#delConfirm').onclick = async () => {
        try {
            await request(`/api/admin/users/${delId}`, { method: 'DELETE' });
            hideDelModal(); loadTable(); alert('删除成功');
        } catch (e) { alert('删除失败：' + e.message); }
    };

    /* 查询/重置 */
    $('#searchBtn').onclick = () => { currPage = 1; loadTable(); };
    $('#resetBtn').onclick = () => {
        $('#keyword').value = '';
        $('#statusFilter').value = '';
        currPage = 1;
        loadTable();
    };

    /* 头像上传预览 */
    $('#avatarUploadBox').onclick = () => $('#avatarFile').click();
    $('#avatarFile').onchange = e => {
        const file = e.target.files[0];
        if (!file) return $('#avatarPreview').classList.add('hidden');
        const reader = new FileReader();
        reader.onload = ev => {
            $('#avatarPreview img').src = ev.target.result;
            $('#avatarPreview').classList.remove('hidden');
        };
        reader.readAsDataURL(file);
    };

    /* 初始加载 */
    window.onload = () => loadTable();
</script>
</body>
</html>
